// Quantitative Angiogram Analysis System
//
// Copyright ?Ping Zou, 2006
// sg71.cherub@gmail.com

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

using WeifenLuo.WinFormsUI;
using eee.Sheffield.PZ.Imaging;
using eee.Sheffield.PZ.Imaging.ImageIO;
using eee.Sheffield.PZ.Imaging.ImageFilter;
using eee.Sheffield.PZ.Math;

namespace eee.Sheffield.PZ.QAAS
{
    /// <summary>
    /// class ImageDoc menu item events
    /// </summary>
    partial class ImageDoc
    {
        /// <summary>
        /// Image -> Crop
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cropToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Crop cropFilter = new Crop();
            cropFilter.NewHeight = 50;
            cropFilter.NewWidth = 50;
            cropFilter.UpRightCorner = new PZPoint(110, 120);
            ApplyImageFilter(cropFilter);
            Log();
        }

        #region Intensity
        /// <summary>
        /// Image -> Intensity -> Negative
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void negativeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new Negative());
            // log
            Log();
        }

        /// <summary>
        /// Image -> Intensity -> Line Enhancement
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lineEnhancementToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new LineEnhancement());
            Log();
        }

        #endregion

        #region Morphology
        /// <summary>
        /// Image -> Morphology -> Peter Thinning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void peterThinningToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new RockettThinning());
            // log
            Log();
        }

        /// <summary>
        /// Image -> Morphology -> Detect Triple Junctions
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void detectTripleJunctionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TripleJunctionDetector filter = new TripleJunctionDetector();
            Bitmap srcImage = (Bitmap)this.Image.Clone();
            //eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo24bppRGB(ref srcImage);
            ApplyImageFilter(filter);
            ShowImage(filter.TripleJunctionImage(srcImage), "Triple Junction");
            filter.WriteFile("triple junction.txt");
            Log();
        }

        /// <summary>
        /// Image -> Morphology -> Detect Free Ends
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void detectFreeEndsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FreeEndDetector filter = new FreeEndDetector();
            Bitmap srcImage = (Bitmap)this.Image.Clone();
            ApplyImageFilter(filter);
            ShowImage(filter.FreeEndImage(srcImage), "Free Ends");
            filter.WriteFile("free ends.txt");
            Log();
        }

        /// <summary>
        /// Image -> Morphology -> Split Line Segment
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void splitLineSegmentsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // detect junction point list
            TripleJunctionDetector junctionDetector = new TripleJunctionDetector();
            Bitmap srcImage = (Bitmap)this.Image.Clone();
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref srcImage);
            junctionDetector.ApplyGraylevelImageFilter(srcImage);
            // detect end point list
            FreeEndDetector freeEndDetector = new FreeEndDetector();
            freeEndDetector.ApplyGraylevelImageFilter(srcImage);
            // split line segments
            LineSegmentSplitter splitter = new LineSegmentSplitter(freeEndDetector.FreeEndList, junctionDetector.TripleJunctionList);
            splitter.ApplyGraylevelImageFilter(srcImage);
            ShowImage(splitter.LineSegmentImage(srcImage), "Line Segments");
            Log();
        }

        /// <summary>
        /// Image -> Morphology -> Dilation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void diationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new Dilation());
            Log();
        }

        /// <summary>
        /// Image -> Morphology -> Erosion
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void erosionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new Erosion());
            Log();
        }


        /// <summary>
        /// Image -> Morphology -> Closing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void closingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new Closing());
            Log();
        }

        /// <summary>
        /// Image -> Morphology -> Opening
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void openingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new Opening());
            Log();
        }

        /// <summary>
        /// Image -> Morphology -> GVF Thinning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gVFThinningToolStripMenuItem1_Click(object sender, EventArgs e)
        {            
            DateTime prepareStart = DateTime.Now;

            // prepare srcImage;
            Bitmap srcImage = (Bitmap)_image.Clone();
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref srcImage);
            
            string tempFolderName = Directory.GetCurrentDirectory() + "\\GVF thinning temp files";
            Directory.CreateDirectory(tempFolderName);
            // log
            string logFileName = tempFolderName + "\\log.txt";
            FileStream logFileStream = new FileStream(logFileName, FileMode.Create, FileAccess.Write);
            StreamWriter logStreamWriter = new StreamWriter(logFileStream);

            string adaptiveSmoothImageFileName = tempFolderName + "\\adaptive smooth.bmp";
            string GVFUFileName = tempFolderName + "\\GVF U.txt";
            string GVFVFileName = tempFolderName + "\\GVF V.txt";
            string GVFVectorMagnitudeFileName = tempFolderName + "\\GVF Vector Magnitude.txt";
            string bwCloseImageFileName = tempFolderName + "\\bw close.bmp";
            string thinImageFileName = tempFolderName + "\\thin.bmp";
            string freeEndFileName = tempFolderName + "\\free ends.txt";
            string junctionFileName = tempFolderName + "\\junction.txt";

            // adaptive smooth            
            Bitmap adaptiveSmoothImage = null;
            if (!File.Exists(adaptiveSmoothImageFileName))
            {
                AdaptiveSmooth adaptiveSmoothFilter = new AdaptiveSmooth();
                adaptiveSmoothImage = adaptiveSmoothFilter.ApplyGraylevelImageFilter(srcImage);
                //eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref adaptiveSmoothImage);
                adaptiveSmoothImage.Save(adaptiveSmoothImageFileName);
            }
            else
            {
                adaptiveSmoothImage = new Bitmap(adaptiveSmoothImageFileName);
                eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref adaptiveSmoothImage);
            }

            //Console.WriteLine("Adaptive smooth DONE.");
            logStreamWriter.WriteLine("Adaptive smooth DONE.");

            // GVF            
            PZMath_matrix GVFUMatrix = null;
            PZMath_matrix GVFVMatrix = null;
            PZMath_matrix GVFVectorMagnitudeMatrix = null;
            if (!File.Exists(GVFUFileName) || !File.Exists(GVFVFileName) || !File.Exists(GVFUFileName))
            {
                double sigma = 1.0;
                double mu = 0.2;
                GradientVectorFlow gvfFilter = new GradientVectorFlow(sigma, mu);
                gvfFilter.ApplyGraylevelImageFilter(srcImage);
                GVFVMatrix = gvfFilter.V;
                GVFUMatrix = gvfFilter.U;
                GVFVectorMagnitudeMatrix = gvfFilter.VectorMagnitude;
                gvfFilter.WriteFileU(GVFUFileName);
                gvfFilter.WriteFileV(GVFVFileName);
                gvfFilter.WriteFileVectorMagnitude(GVFVectorMagnitudeFileName);
            }
            else
            {
                GVFUMatrix = new PZMath_matrix(GVFUFileName);
                GVFVMatrix = new PZMath_matrix(GVFVFileName);
                GVFVectorMagnitudeMatrix = new PZMath_matrix(GVFVectorMagnitudeFileName);
            }
            logStreamWriter.WriteLine("GVF DONE.");
            //Console.WriteLine("GVF DONE.");

            // SIS threshold
            int sisThreshold = 0;
            Bitmap bwImage = null;
            SISThreshold sisThresholdFilter = new SISThreshold();
            sisThresholdFilter.LogWriter = logStreamWriter;
            bwImage = sisThresholdFilter.ApplyGraylevelImageFilter(adaptiveSmoothImage);
            sisThreshold = sisThresholdFilter.Threshold;
            logStreamWriter.WriteLine("SIS threshold DONE.");
            //Console.WriteLine("SIS threshold DONE.");

            // closing            
            Bitmap bwCloseImage = null;
            if (!File.Exists(bwCloseImageFileName))
            {
                eee.Sheffield.PZ.Imaging.ImageFilter.Closing closeFilter = new Closing();
                bwCloseImage = closeFilter.ApplyGraylevelImageFilter(bwImage);
                //eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref bwCloseImage);
                bwCloseImage.Save(bwCloseImageFileName);
            }
            else
            {
                bwCloseImage = new Bitmap(bwCloseImageFileName);
                eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref bwCloseImage);
            }
            logStreamWriter.WriteLine("Closing DONE.");
            //Console.WriteLine("Closing DONE.");

            // Peter thinning            
            Bitmap thinImage = null;
            if (!File.Exists(thinImageFileName))
            {
                RockettThinning thinFilter = new RockettThinning();
                thinImage = thinFilter.ApplyGraylevelImageFilter(bwCloseImage);
                //eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref thinImage);
                thinImage.Save(thinImageFileName);
            }
            else
            {
                thinImage = new Bitmap(thinImageFileName);
                eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref thinImage);
            }
            logStreamWriter.WriteLine("Peter thinning DONE.");
            //Console.WriteLine("Peter thinning DONE.");

            // split line segments            
            FreeEndDetector freeEndDetector = new FreeEndDetector();
            if (!File.Exists(freeEndFileName))
            {
                freeEndDetector.ApplyGraylevelImageFilter(thinImage);
                freeEndDetector.WriteFile(freeEndFileName);
            }
            else
            {
                freeEndDetector.ReadFile(freeEndFileName);
            }                         
            TripleJunctionDetector junctionDetector = new TripleJunctionDetector();
            if (!File.Exists(junctionFileName))
            {
                junctionDetector.ApplyGraylevelImageFilter(thinImage);
                junctionDetector.WriteFile(junctionFileName);
            }
            else
            {
                junctionDetector.ReadFile(junctionFileName);
            }            

            LineSegmentSplitter splitter = new LineSegmentSplitter(freeEndDetector.FreeEndList, junctionDetector.TripleJunctionList);
            splitter.ApplyGraylevelImageFilter(thinImage);
            logStreamWriter.WriteLine("Split line segments DONE.");
            //Console.WriteLine("Split line segments DONE.");

            DateTime prepareEnd = DateTime.Now;
            TimeSpan prepareDuration = prepareEnd - prepareStart;

            DateTime MCMCStart = DateTime.Now;
            // MCMC
            LineSegmentConfiguration c = new LineSegmentConfiguration(splitter.LineSegmentList);
            c.InitLineSegmentIndex();
            c.AssignDataTerm(srcImage, GVFUMatrix, GVFVMatrix, GVFVectorMagnitudeMatrix);

            // parameters
            c.W1 = -0.5;       // # of line segments
            c.W2 = 1;       // # of free line segments
            c.W3 = 1;       // # of free ends
            c.WC = 1;     // connection
            c.WL = 0.5;     // length
            c.WG = 0.6;     // Gs value
            c.WI = 0.6;     // Is value

            c.Gt = 0.70;
            c.It = sisThreshold;
            c.KI = 1;

            // prepare MCMC GVF sampler
            int total = 40000;
            int burnin = 1000;
            int space = 100;
            MCMCGVFThinning gvfThinningFilter = new MCMCGVFThinning(srcImage, GVFUMatrix, GVFVMatrix, GVFVectorMagnitudeMatrix, c, total, burnin, space);
            gvfThinningFilter.Sampler.LogWriter = logStreamWriter;
            // do MCMC, dstImage is the line segments with high hit probability            
            PZMath_matrix dstMatrix = gvfThinningFilter.ApplyDoubleGraylevelImageFilter(new PZMath_matrix(1, 1));

            ConvertBitmapMatrix converter = new ConvertBitmapMatrix();
            Bitmap hittingProbabilityImage = converter.ConvertMatrixToGraylevelBitmap(dstMatrix, true);
            logStreamWriter.WriteLine("MCMC DONE.");
            //Console.WriteLine("MCMC DONE.");

            hittingProbabilityImage.Save(tempFolderName + "//hit.bmp");

            // invert and threshold MCMC result
            string resultImageFileName = Directory.GetCurrentDirectory() + "//result.bmp";

            sisThresholdFilter.ApplyGraylevelImageFilter(hittingProbabilityImage);
            int threshold = Convert.ToInt16(sisThresholdFilter.Threshold * 1.5);
            
            //Console.WriteLine(sisThresholdFilter.Threshold);
            //Console.WriteLine(threshold);

            Threshold thresholdFilter = new Threshold(threshold);
            Bitmap thresholdImage = thresholdFilter.ApplyGraylevelImageFilter(hittingProbabilityImage);

            //thresholdImage.Save("threshold.bmp");

            Negative negativeFilter = new Negative();
            Bitmap resultImage = negativeFilter.ApplyGraylevelImageFilter(thresholdImage);
            //eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref resultImage);
            resultImage.Save(resultImageFileName);

            // display result (thresholded hitting probability map)
            ShowImage(resultImage, "GVF thinning");

            DateTime MCMCEnd = DateTime.Now;
            TimeSpan MCMCDuration = MCMCEnd - MCMCStart;

            // evaluate result
            string manualImageFileName = Directory.GetFiles(Directory.GetCurrentDirectory(), "*manual*.bmp")[0]; // "//manual centre line.bmp";
            if (File.Exists(manualImageFileName))
            {
                Bitmap manualImage = new Bitmap(manualImageFileName);
                eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref manualImage);
                EvaluateThinningByManualSegmentation evaluator = new EvaluateThinningByManualSegmentation(resultImage, manualImage);
                evaluator.EvaluateResult();
                logStreamWriter.WriteLine(evaluator.FValue);
                logStreamWriter.WriteLine(evaluator.OValue);
                Log(evaluator.FValue);
                Log(evaluator.OValue);
            }
            else
            {
                MessageBox.Show("manual result does not exist. No evaluation.");
            }
            logStreamWriter.WriteLine("Evaluate DONE.");
            logStreamWriter.WriteLine("prepare time: " + prepareDuration);
            logStreamWriter.WriteLine("MCMC time: " + MCMCDuration);
            logStreamWriter.WriteLine("GVF thinning succeed.");
            logStreamWriter.Flush();
            logStreamWriter.Close();
            logFileStream.Close();
            //Console.WriteLine("Evaluate DONE.");
            //Console.WriteLine("prepare time: " + prepareDuration);
            //Console.WriteLine("MCMC time: " + MCMCDuration);
            Log("GVF thinning succeed.");
        }        
        #endregion

        #region Threshold
        /// <summary>
        /// Image -> Threshold -> Threhold
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void thresholdToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            UseFilterForm(FilterFormType.Threshold);
        }


        /// <summary>
        /// Image -> Threshold -> SIS Threshold
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sISThresoldToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new SISThreshold());
            // log
            Log();
        }

        /// <summary>
        /// Image -> Threshold -> Flood Fill
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void floodFillToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UseFilterForm(FilterFormType.FloodFill);
        }
        #endregion

        #region Gradient
        /// <summary>
        /// Image -> Gradient -> Sobel X
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sobelXToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new SobelX());
            // log
            Log();
        }
        /// <summary>
        /// Image -> Gradient -> Sobel Y
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sobelYToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new SobelY());
            // log
            Log();
        }
        /// <summary>
        /// Image -> Gradient -> Laplacian
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void laplacianToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new DiscreteLaplacian());
            // log
            Log();
        }
        /// <summary>
        /// Image -> Gradient -> Central Difference X
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void centralDifferenceXToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new GradientXCentralDifference());
            // log
            Log();
        }
        /// <summary>
        /// Image -> Gradient -> Central Difference Y
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void centralDifferenceYToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new GradientYCentralDifference());
            // log
            Log();
        }

        /// <summary>
        /// Image -> Gradient -> Edge Map
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void edgeMapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new EdgeMap(5));
            // log
            Log();
        }

        /// <summary>
        /// Image -> Gradient -> Gradient Vector Flow
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gradientVectorFlowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UseFilterForm(FilterFormType.GVF);
        }


        /// <summary>
        /// Image -> Gradient -> Ridge
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ridgeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new FixScaleRidgeDetection(2));
            Log();
        }
        #endregion

        #region Smooth
        /// <summary>
        /// Image -> Smooth -> Gaussian Smooth
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gaussianSmoothToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new GaussianSmoothing(1));
            // log
            Log();
        }
        /// <summary>
        /// Image -> Smooth -> Gaussian Smooth X
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gaussinSmoothXToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new GaussianX(1));
            // log
            Log();
        }
        /// <summary>
        /// Image -> Smooth -> Gaussian Smooth Y
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gaussinSmoothYToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new GaussianY(1));
            // log
            Log();
        }

        /// <summary>
        /// Image -> Smooth -> Adaptive Smooth 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void adaptiveSmoothToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new AdaptiveSmooth());
            Log();
        }

        /// <summary>
        /// Image -> Smooth -> Median
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void medianToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UseFilterForm(FilterFormType.MedianSmooth);
        }
        #endregion

        #region Multiresolution Operators
        /// <summary>
        /// Multiresolution Operators -> Reduce
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void reduceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new ReduceResolution());
            Log();
        }

        /// <summary>
        /// Multiresolution Operators -> Expand
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void expandToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new ExpandResolution());
            Log();
        }
        #endregion

        #region Test                                        
        /// <summary>
        /// 9. Test -> Is Value Map
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void isValueMapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string myDocumentDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
            string folderName = myDocumentDirectoryName + "\\My C#\\Test Images\\";   

            string thinningFileName = folderName + "0000_thinning.pgm";
            string originalImageFileName = folderName + "0000_original.pgm";
            ImageDoc originalImageDoc = new ImageDoc(originalImageFileName);

            // threshold
            SISThreshold thresholdFilter = new SISThreshold();
            thresholdFilter.ApplyGraylevelImageFilter(originalImageDoc.Image);
            string thresholdLogText = thresholdFilter.LogText;
            int intensityThreshold = thresholdFilter.Threshold;
            Log(thresholdLogText);

            // gvf
            double sigma = 1.0;
            double mu = 0.2;
            GradientVectorFlow gvfFilter = new GradientVectorFlow(sigma, mu);
            gvfFilter.ApplyGraylevelImageFilter(originalImageDoc.Image);
            Log(gvfFilter.LogText);

            // thinning and line segments
            RockettThinning thinningFilter = new RockettThinning();
            ImageDoc thinningImageDoc = new ImageDoc(thinningFileName);
            //thinningFilter.SplitThinningResult(thinningImageDoc.Image);
            Log(thinningFilter.LogText);

            // configurate
            string filterLogText = "";
            LineSegmentConfiguration c = new LineSegmentConfiguration(thinningFilter.LineSegmentList);
            // TODO: assigne data term
            //c.AssignDataTerm(originalImageDoc.Image, gvfFilter.U, gvfFilter.V, gvfFilter.VectorMagnitude);
            double kI = 1.2;
            double It = (double)thresholdFilter.Threshold / kI;
            ShowImage(c.DrawIsThreshold(originalImageDoc.Image, It), "Is");
            //ShowImage(c.DrawGsThreshold(originalImageDoc.Image), "Gs");
            //c.ObserveGs(intensityThreshold);
            //c.WriteGsFile("gs.txt");
            //c.WritePGFile("pg.txt");
            filterLogText = "Gs value map: plot Gs threshold line segments";
            Log(filterLogText);
        }

        /// <summary>
        /// 10. Test -> GVF Thinning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gVFThinningToolStripMenuItem_Click(object sender, EventArgs e)
        {            
            DateTime startTime = DateTime.Now;
            //string myDocumentDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
            //string folderName = myDocumentDirectoryName + "\\My C#\\Imaging\\Example Images\\Threshold\\Gradient Vector Field\\";           
            //string thinningImageFileName = folderName + "0000_thinning.pgm";            
            //string originalImageFileName = folderName + "0000_original.pgm";

            string myDesktopDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
            string folderName = myDesktopDirectoryName + "\\New Folder (4)\\";
            string thinningImageFileName = folderName + "image 4_thin.bmp";
            string originalImageFileName = folderName + "image 4.bmp";
            string freeEndListFileName = folderName + "free ends.txt";
            string junctionListFileName = folderName + "triple junction.txt";
            string GVFVFileName = folderName + "GVFV.txt";
            string GVFUFileName = folderName + "GVFU.txt";
            string GVFVectorMagnitudeFileName = folderName + "GVFVectorMagnitude.txt";

            ImageDoc originalImageDoc = new ImageDoc(originalImageFileName);
            ImageDoc thinningImageDoc = new ImageDoc(thinningImageFileName);
            Bitmap srcImage = (Bitmap)originalImageDoc.Image.Clone();
            Bitmap thinningImage = (Bitmap)thinningImageDoc.Image.Clone();

            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref srcImage);
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref thinningImage);    
            //TaskMCMCGVFThinning taskMCMCGVFThinning = new TaskMCMCGVFThinning(srcImage, thinningImage);
            TaskMCMCGVFThinning taskMCMCGVFThinning = new TaskMCMCGVFThinning(srcImage, thinningImage, freeEndListFileName, junctionListFileName,
                GVFVFileName, GVFUFileName, GVFVectorMagnitudeFileName);

            // line segments' hitting probability map
            Bitmap dstImage = taskMCMCGVFThinning.Apply(originalImageDoc.Image);
            ShowImage(dstImage, "MCMC GVF thinning");

            // get line segment configuration with max intensity
            //taskMCMCGVFThinning.MCMCGVFThinningFilter.Sampler.GetLineSegmentConfigurationWithMinU();
            //LineSegmentConfiguration lineSegmentConfigurationWithMaxH = taskMCMCGVFThinning.MCMCGVFThinningFilter.Sampler.LineSegmentConfigurationWithMinU;
            //Bitmap maxHImage = lineSegmentConfigurationWithMaxH.DrawLineSegments(srcImage);
            //ShowImage(maxHImage, "MCMC GVF Thinning Max Intensity");

            DateTime endTime = DateTime.Now;
            TimeSpan duration = endTime - startTime;
            Console.WriteLine("running time: " + duration);
        }

        /// <summary>
        /// 11. Test -> Synthetic Image GVF
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void syntheticImageGVFToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string folderName = "C:\\Documents and Settings\\Cherub\\My Documents\\My C#\\Imaging\\Example Images\\Threshold\\Gradient Vector Field\\";
            //string folderName = "C:\\Documents and Settings\\Cherub\\My Documents\\My Documentary\\Gradient Vector Field and Thinning\\GVF Thinning Test Images\\";
            string thinningFileName = folderName + "0000_thinning.pgm";
            // this skeleton has 3 line segments
            string originalImageFileName = folderName + "0000_original.pgm";
            ImageDoc originalImageDoc = new ImageDoc(originalImageFileName);
            
            #region Prepare source
            // threshold            
            SISThreshold thresholdFilter = new SISThreshold();
            thresholdFilter.ApplyGraylevelImageFilter(originalImageDoc.Image);
            string thresholdLogText = thresholdFilter.LogText;
            int intensityThreshold = thresholdFilter.Threshold;
            //Log(thresholdLogText);

            // gvf
            double sigma = 1.0;
            double mu = 0.2;
            GradientVectorFlow gvfFilter = new GradientVectorFlow(sigma, mu);
            gvfFilter.ApplyGraylevelImageFilter(originalImageDoc.Image);            

            // thinning and line segments
            RockettThinning thinningFilter = new RockettThinning();
            ImageDoc thinningImageDoc = new ImageDoc(thinningFileName);
            //thinningFilter.SplitThinningResult(thinningImageDoc.Image);
            #endregion

            // configurate
            string filterLogText = "";
            LineSegmentConfiguration c = new LineSegmentConfiguration(thinningFilter.LineSegmentList);            
            c.AssignDataTerm(originalImageDoc.Image, gvfFilter.U, gvfFilter.V, gvfFilter.VectorMagnitude);
            c.InitLineSegmentIndex();
            // parameters
            c.W1 = -0.1;
            c.W2 = 1.0;
            c.W3 = 0.1;
            c.WC = 1.0;
            c.WL = 1.0;
            c.WG = 1.0;
            c.WI = 1.0;
            c.Gt = 0.65;
            c.It = thresholdFilter.Threshold;
            c.KI = 1.1;
            c.CalculateUP();
            c.CalculateUD();
            c.CalculateU();
            c.CalculateH();
            c.WriteAllDetails("allDetail.txt");
            //c.SynthethicModelStudy("debugDetail.txt");
            
            filterLogText = "check detail file";
            Log(filterLogText);
        }

        /// <summary>
        /// 12. Test -> Com Scanline Profile Analysis Methods
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comScanlineAnalysisMethosToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string folderName = "C:\\Documents and Settings\\Ping\\My Documents\\My C#\\Test Images\\";
            string fileName = "0000.pgm";

            // get image
            string sourceFileName = folderName + fileName;
            ImageDoc sourceImageDoc = new ImageDoc(sourceFileName);

            // set start and end positions
            PZPoint startPos = new PZPoint(228, 277); //(227.0, 84.0);
            PZPoint endPos = new PZPoint(240, 277); //(245.0, 83.0);
            int distance = (int) System.Math.Ceiling(startPos.Distance(endPos));
            PZDirection direction = new PZDirection(endPos.x - startPos.x, endPos.y - startPos.y);

            // get scanline profile
            PZMath_vector sl = new PZMath_vector(distance);
            for (int i = 0; i < distance; i++)
            {
                int x = (int)(startPos.x + i * direction.x);
                int y = (int)(startPos.y + i * direction.y);
                sl[i] = (double)sourceImageDoc._image.GetPixel(x, y).R;
            }

            // process scanline profile
            ZhouMatchedFilter zhouMatchedFilter = new ZhouMatchedFilter();
            FrameModel frameModel = new FrameModel();
            ZouModel zouModel = new ZouModel();
            string zhouResultFileName = "zhou result.txt";
            string frameResultFileName = "frame result.txt";
            string zouResultFileName = "zou result.txt";
            
            // Zhou
            zhouMatchedFilter.ZhouRecord(sl, zhouResultFileName);
            // Frame
            double initr = (double)distance / 4.0;
            frameModel.FrameRecord(initr, sl, frameResultFileName);            
            // Zou
            int widthOfScanline = distance;         
            int sampleRate = 1;
            double c = (double)distance / 2.0;
            initr = c / 2.0;
            double mu = 0.1;
            double B = 25;
            PZScanline scanline = new PZScanline(widthOfScanline, sampleRate, c, initr, mu, B);
            for (int i = 0; i < widthOfScanline; i++)
            {
                scanline._fg[i] = sl[i];
            }
            zouModel.ZouRecord(scanline, zouResultFileName);

            // save scanline profile
            string scanlineProfileFileName = "scanline profile.txt";
            scanline.WriteFile(scanlineProfileFileName);

        }

        /// <summary>
        /// 13. Test -> Test Joined Line Segments
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tempToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string myDocumentDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
            string folderName = myDocumentDirectoryName + "\\My C#\\Imaging\\Example Images\\Threshold\\Gradient Vector Field\\";
            string thinningImageFileName = folderName + "0000_thinning.pgm";

            ImageDoc thinningImageDoc = new ImageDoc(thinningImageFileName);
            Bitmap thinningImage = (Bitmap)thinningImageDoc.Image.Clone();           
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref thinningImage);

            TripleJunctionDetector junctionDetector = new TripleJunctionDetector();
            junctionDetector.ApplyGraylevelImageFilter(thinningImage);
            FreeEndDetector freeEndDetector = new FreeEndDetector();
            freeEndDetector.ApplyGraylevelImageFilter(thinningImage);
            LineSegmentSplitter splitter = new LineSegmentSplitter(freeEndDetector.FreeEndList, junctionDetector.TripleJunctionList);
            splitter.ApplyGraylevelImageFilter(thinningImage);

            // pick line segments
            int[] lineSegmentIndex = RandomIndex.GenerateRandomIndex(300, 400);
            List<LineSegment> randomLineSegmentList = new List<LineSegment>(200);
            for (int i = 0; i < lineSegmentIndex.Length; i++)
                randomLineSegmentList.Add(splitter.LineSegmentList[lineSegmentIndex[i]]);

            // merge line segments
            LineSegmentConfiguration c = new LineSegmentConfiguration(randomLineSegmentList);
            c.JoinSegments();
            LineSegmentConfiguration cJoined = new LineSegmentConfiguration(c.JoinedConfiguration);

            // display images
            ShowImage(c.DrawLineSegments(thinningImage), "line segments");
            ShowImage(cJoined.DrawLineSegments(thinningImage), "joined segments");            

        }


        /// <summary>
        /// 14. Test -> Task, get removed line segments Gs/Cs histogram
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void taskGetRemovedLineSegmentsGsCsHistogramToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string myDesktopDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
            string folderName = myDesktopDirectoryName + "\\New Folder (3)\\";

            // get removed line segments
            string allImageFileName = folderName + "image_thin.bmp";
            string manualImageFileName = folderName + "manual.bmp";

            TaskGetRemovedLineSegments task = new TaskGetRemovedLineSegments(allImageFileName, manualImageFileName);
            List<LineSegment> removedLineSegmentsList = task.GetRemovedLineSegments();

            // get GVF           
            string GVFVFileName = folderName + "GVFV.txt";
            string GVFUFileName = folderName + "GVFU.txt";
            string GVFVectorMagnitudeFileName = folderName + "GVFVectorMagnitude.txt";
            GradientVectorFlow gvfFilter = new GradientVectorFlow();
            gvfFilter.ReadFileU(GVFUFileName);
            gvfFilter.ReadFileV(GVFVFileName);
            gvfFilter.ReadFileVectorMagnitude(GVFVectorMagnitudeFileName);

            string originalImageFileName = folderName + "image3.bmp";
            ImageDoc originalImageDoc = new ImageDoc(originalImageFileName);
            Bitmap srcImage = (Bitmap)originalImageDoc.Image.Clone();
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref srcImage);
            LineSegmentConfiguration c = new LineSegmentConfiguration(removedLineSegmentsList);
            c.AssignDataTerm(srcImage, gvfFilter.U, gvfFilter.V, gvfFilter.VectorMagnitude);

            // get Gs and histogram
            c.WriteGsHistogram("gsHistogram.txt");
            c.WriteGsListHistogram("gsListHistogram.txt");
            c.WriteAngleHistogram("angleHistogram.txt");
            c.WriteAngleListHistogram("angleListHistogram.txt");

            // get Cs and histogram
            c.CalculatePC();
            c.WriteCsHistogram("csHistogram.txt");
            c.WritePCHistogram("pcHistogram.txt");

            Bitmap removedLineSegmentImage = c.DrawLineSegments(srcImage);
            ShowImage(removedLineSegmentImage, "removed line segments");
            Log("Taks done");
        }

        /// <summary>
        /// Teset -> 15. Evaluate GVF Thinning results
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void evaluateGVFThinningResultsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UseFilterForm(FilterFormType.GVFThinning);

            
            //string myDesktopDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
            //string folderName = myDesktopDirectoryName + "\\New Folder (4)\\";

            //// get removed line segments
            //string resultImageFileName = folderName + "result.bmp";
            //string manualImageFileName = folderName + "manual.bmp";

            //EvaluateThinningByManualSegmentation evaluator = new EvaluateThinningByManualSegmentation(resultImageFileName, manualImageFileName);
            //evaluator.EvaluateResult();

            //string strTruePositive = "True Positive Rate:" + evaluator.TruePositive.ToString();
            //string strTrueNegative = "True Negative Rate:" + evaluator.TrueNegative.ToString();
            //string strFalsePositive = "False Positive Rate (Type I Error):" + evaluator.FalsePositive.ToString();
            //string strFalseNegative = "False Negative Rate (Type II Error):" + evaluator.FalseNegative.ToString();

            //Log(folderName);
            //Log(evaluator.FValue);
            //Log(evaluator.OValue);

            //Log(strTruePositive);
            //Log(strTrueNegative);
            //Log(strFalsePositive);
            //Log(strFalseNegative);

            //Log("another");

            // get removed line segments
            //resultImageFileName = folderName + "result.bmp";
            //manualImageFileName = folderName + "manual_1.bmp";

            //EvaluateThinningByManualSegmentation evaluator2 = new EvaluateThinningByManualSegmentation(resultImageFileName, manualImageFileName);
            //evaluator2.EvaluateResult();
            //Log(evaluator.FValue);
            //Log(evaluator.OValue);

            //strTruePositive = "True Positive Rate:" + evaluator2.TruePositive.ToString();
            //strTrueNegative = "True Negative Rate:" + evaluator2.TrueNegative.ToString();
            //strFalsePositive = "False Positive Rate (Type I Error):" + evaluator2.FalsePositive.ToString();
            //strFalseNegative = "False Negative Rate (Type II Error):" + evaluator2.FalseNegative.ToString();

            //Log(strTruePositive);
            //Log(strTrueNegative);
            //Log(strFalsePositive);
            //Log(strFalseNegative);

        }

        /// <summary>
        /// Test -> 16. Task Median smooth with ROI
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void taskMedianSmoothWithROIToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string myDesktopDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
            string folderName = myDesktopDirectoryName + "\\New Folder (8)\\";
            string srcImageFileName = folderName + "image 8_g.bmp";
            string maskImageFileName = folderName + "image 8_mask.bmp";

            // get srcImage
            ImageDoc srcImageDoc = new ImageDoc(srcImageFileName);
            Bitmap srcImage = (Bitmap)srcImageDoc.Image.Clone();
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref srcImage);

            // get maskImage and ROIMatrix
            ImageDoc maskImageDoc = new ImageDoc(maskImageFileName);
            Bitmap maskImage = (Bitmap)maskImageDoc.Image.Clone();
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref maskImage);
            ConvertBitmapMatrix converter = new ConvertBitmapMatrix();
            PZMath_matrix ROIMatrix = converter.GetROIMatrix(maskImage);

            // median filter
            int radius = 21;
            int percentile = 50;
            Median filter = new Median(radius, percentile, ROIMatrix);
            Bitmap dstImage = filter.ApplyGraylevelImageFilter(srcImage);
            string caption = "radius: " + radius + " percentil: " + percentile;
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref dstImage);
            ShowImage(dstImage, caption);
            Log("Median filter: " + caption);
        }

        /// <summary>
        /// Test -> 17. Task Preprocess DRIVE image
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void taskPreprocessDRIVEImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string myDesktopDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
            string folderName = myDesktopDirectoryName + "\\New Folder (8)\\";
            string srcImageFileName = folderName + "image 8.bmp";
            string maskImageFileName = folderName + "image 8_mask.bmp";
            string manualImageFileName = folderName + "image 8_manual.bmp";

            Bitmap srcImage = new Bitmap(srcImageFileName);
            Bitmap maskImage = new Bitmap(maskImageFileName);
            Bitmap manualImage = new Bitmap(manualImageFileName);
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref maskImage);
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref manualImage);

            TaskPreprocessDriveImage preprocessFilter = new TaskPreprocessDriveImage(srcImage, maskImage, manualImage);
            preprocessFilter.Preprocess();
            preprocessFilter.WriteDSAImage("DSA image.bmp");
            preprocessFilter.WriteManualCentreLineImage("manual centre line.bmp");
            ShowImage(preprocessFilter.DSAImage, "DSA Image");
            ShowImage(preprocessFilter.ManualCentreLineImage, "manual centre line iamge");
        }

        /// <summary>
        /// Test -> 18. Task FO
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void taskFOToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string myDesktopDirectoryName = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
            string folderName = myDesktopDirectoryName + "\\for song";
            string srcImageFileName = folderName + "\\GVF thinning temp files\\adaptive smooth.bmp";
            string manualImageFileName = folderName + "\\manual.bmp";
            Bitmap srcImage = new Bitmap(srcImageFileName);
            Bitmap manualImage = new Bitmap(manualImageFileName);
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref srcImage);
            eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref manualImage);

            TaskFO taskFO = new TaskFO(srcImage, manualImage);
            taskFO.FO();
        }
        #endregion

        #region Colour
        /// <summary>
        /// Image -> Colour -> R Channel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rChannelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new ColourChannel(ColourChannelEnum.R));
            Log("R channel displayed.");
        }

        /// <summary>
        /// Image -> Colour -> G Channel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gChannelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new ColourChannel(ColourChannelEnum.G));
            Log("G channel displayed.");
        }

        /// <summary>
        /// Image -> Colour -> B Channel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bChannelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplyImageFilter(new ColourChannel(ColourChannelEnum.B));
            Log("B channel displayed.");
        }
        #endregion

        #region Two images
        /// <summary>
        /// Image -> Two Images...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void twoImagesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UseFilterForm(FilterFormType.TwoImages);
        }
        #endregion

        #region Track Vessel Newtork
        /// <summary>
        /// Track Vessel Network -> Zou&Rockett Track
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tryTrackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UseFilterForm(FilterFormType.ZouRockettTracking);
        }

        /// <summary>
        ///  Track Vessel Network -> Liu&Sun Track
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void liuSunTrackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TaskTryLiuSunTracking tryTrack = new TaskTryLiuSunTracking();
            Bitmap dstImage = tryTrack.Apply(this._image);
            ShowImage(dstImage, "Liu&Sun Track Result");
        }
        #endregion

        #region Short cut
        private void shortCutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UseFilterForm(FilterFormType.GVFThinning);
        }
        #endregion
    }
}
